#ifndef __CONCURRENT_POOL__
#define __CONCURRENT_POOL__
// 高并发内存池 - 面向用户层封装的一个空间

#include "DefiniteLengthMemoryPool.hpp"
#include "ThreadCache.hpp"


namespace QiHai
{
	// 申请内存 - byte为单位
	static void* ConcurrentAlloc(size_t bytes)
	{
		void* ptr = nullptr;
		// bytes <= 256kb = 256 * 1024 小块内存划分，走三层结构
		if (bytes <= MAX_BYTES)
		{
			// 因为申请的内存千变万化，我们需要控制合理的对齐字节数 进行分配内存
			// 每个线程申请到这里，需要保证线程缓存是独立的。-利用TLS技术，线程本地存储，不实现共享
			if (TLSThradObj == nullptr)
			{
				static DefinitePoll<ThreadCache> tcPoll;
				TLSThradObj = tcPoll.New();  // 完全抛弃new哦
			}
			ptr = TLSThradObj->Allocate(bytes);
		}
		else  // 如果大于256kb(64page) 小于 128page(128*4*1024)只走pagecache结构
		{
			// 大于256kb，向pagecache进行申请
			// 如果32 page 小于 128page，根据pagecache中的span申请即可
			// 如果大于128page，我们直接向系统进行申请
			size_t byte = QiHai::SizeClass::RoundUp(bytes);
			Span* span = QiHai::PageCache::PageCacheObj()->NewSpan(byte >> SHIFT_PAGE);
			span->_objNum = byte;
			ptr = (void*)(span->_pageNum << SHIFT_PAGE);
		}

		return ptr;
	}

	// 释放内存
	static bool ConcurrentFree(void* ptr)
	{
		// 首先找是否存在匹配的Span，以便计算此地址的类型大小
		Span* tmp = PageCache::PageCacheObj()->MapObjectToSpan(ptr);
		if (tmp == nullptr) return false;

		if (tmp->_objNum <= MAX_BYTES)
		{
			// 按正常走三层模型
			assert(TLSThradObj);
			TLSThradObj->Deallocate(ptr, tmp->_objNum);
		}
		else {
			PageCache::PageCacheObj()->ReleaseSpanToPageCache(tmp);  // 否则直接走pagecache层
		}
		return true;
	}


}


#endif
